﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using JetBrains.Annotations;

namespace com.susi.util {
    public static class ObjectExtensions {
        /// <summary>
        ///     如果空就返回 "(nil)"，否则返回obj.ToString()
        /// </summary>
        public static string ToString_Debug(this object obj)
        {
            if (obj == null) return "(nil)";
            return obj.ToString();
        }

        /// <summary>
        ///     将单个元素包装成可遍历体;对null值返回Empty
        /// </summary>
        public static IEnumerable<T> WarpAsOneElementEnumerable<T>(this T obj) where T : class
        {
            return obj is null ? Enumerable.Empty<T>() : new[] {obj};
        }

        /// <summary>
        ///     将单个元素包装成拥有1个元素的数组
        /// 不判空
        /// </summary>
        public static T[] WarpAsOneElementArray<T>(this T obj)
        {
            return new[] {obj};
        }

        public static bool TryGetFieldOrProperty<T>(this object ins, string name, out T res)
        {
            return ReflectionUtil.TryGetFieldOrProperty(ins, name, out res);
        }

        [Obsolete("see TrySetFieldOrProperty ExceptionVersion")]
        public static bool TrySetFieldOrProperty<T>(this object ins, string name, T value)
        {
            return ReflectionUtil.TrySetFieldOrProperty(ins, name, value);
        }

        [Obsolete("see TrySetFieldOrProperty ExceptionVersion")]
        public static bool TrySetFieldOrProperty(this object ins, string name, object value, Type valuetype)
        {
            return ReflectionUtil.TrySetFieldOrProperty(ins, name, value, valuetype);
        }

        /// <summary>
        ///     抛异常版
        /// </summary>
        public static bool TrySetFieldOrProperty(this object ins, string name, object value)
        {
            return ReflectionUtil.TrySetFieldOrProperty(ins, name, value);
        }


        /// <summary>
        ///     如果调用失败会返回null。不保证没有歧义，要无歧义调用要用<see cref="ReflectionUtil.TryInvokeMethod" />
        /// </summary>
        public static dynamic InvokeMethod(this object ins, string name, object[] args)
        {
            if (ReflectionUtil.TryInvokeMethod(ins, name, args, out var res)) return res;

            return null;
        }

        /// <summary>
        ///     反射获取<see cref="DescriptionAttribute.Description" />，只能根据类型获取
        /// </summary>
        public static string GetDescriptionStrByAttribute(this object obj, string membername)
        {
            var type  = obj.GetType();
            var field = type.GetField(membername);
            if (field != null) {
                var atr = field.GetCustomAttribute<DescriptionAttribute>();
                return atr?.Description;
            }

            var property = type.GetField(membername);
            // ReSharper disable once InvertIf
            if (property != null) {
                var atr = property.GetCustomAttribute<DescriptionAttribute>();
                return atr?.Description;
            }

            return null;
        }

        /// <summary>
        ///     反射获取<see cref="DescriptionAttribute.Description" />，根据Enum获取
        /// </summary>
        [CanBeNull]
        public static string GetDescriptionStrByAttribute([NotNull] this Enum @enum)
        {
            var type  = @enum.GetType();
            var field = type.GetField(@enum.ToString());
            var atr   = field.GetCustomAttribute<DescriptionAttribute>();
            return atr?.Description;
        }
    }
}